package informationplatform.product


import informationplatform.User
import informationplatform.overtime.Audited;

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellStyle
import org.apache.poi.ss.usermodel.Font
import org.apache.poi.ss.usermodel.IndexedColors
import org.apache.poi.ss.usermodel.Row
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.util.CellRangeAddress
import java.text.SimpleDateFormat

class ProductHistoryService {
	static transactional = true
	def messageSource

	private static final PVERSION_PREFIX = "      |-"
	private static final MILESTON_PREFIX = "            |-"
	private static final FUNCTION_PREFIX = "                  |-"
	/**
	 * 只记录路标子系统的更新日志
	 * 
	 * @param targetObj
	 * @param reporter
	 */
	void logUpdateHistory(Object targetObj) {
		def dirtFields = targetObj.getDirtyPropertyNames()
		def targertType = GuidepostObject.mappingClass(targetObj.class)
		if(!targertType){
			targertType = targetObj.class.name
		}

		if(!dirtFields){
			return;
		}

		def sf = new SimpleDateFormat("yyyy-MM-dd")

		//-----------------------------开始记录日志---------------------------
		def changedContent=''

		dirtFields.each {fieldName->
			if('audited'.equals(fieldName)|| fieldName=='origins'  || fieldName.endsWith("Id")|| fieldName.equals("productVersions")|| fieldName.equals("funcs")){
				return
			}

			def newVal = targetObj."$fieldName"
			def oldVal = targetObj.getPersistentValue(fieldName)

			//值如果是对象, 则对值再深加工一次
			if(newVal instanceof Enum){
				newVal = newVal?.label?:''
				oldVal = oldVal?.label?:''

			}else if(newVal instanceof Date){
				oldVal = oldVal?sf.format(oldVal):''
				newVal = newVal?sf.format(newVal):''

			}else if(newVal instanceof User){
				oldVal = oldVal?.realName?:''
				newVal = newVal?.realName?:''

			}else if(newVal.hasProperty("status")){//有 status属性, 则为路标对象, 一定有name属性
				oldVal = oldVal?.name?:''
				newVal = newVal?.name?:''

			}else if(newVal.hasProperty("product")){
				oldVal = oldVal?.name?:''
				newVal = newVal?.name?:''

			}

			//翻译成中文
			fieldName = translateChinese(fieldName)

			changedContent += "${fieldName}： '${oldVal?:''}' -> '${newVal?:''}'；"
		}

		if(changedContent == ''){//没有变化, 则离开
			return
		}

		def history = new ProductHistory()

		history.targetType = targertType
		history.targetId = targetObj.id
		history.targetName = targetObj.name
		history.fromSt = targetObj.getPersistentValue("status")
		history.toSt = targetObj.status
		history.changedContent = "更新操作： " + changedContent

		//-----------------------------记录treeId---------------------start
		def properties = targetObj.properties
		def treeId=""
		if(properties.guidepostId){
			treeId += (properties.guidepostId + "-")
		}
		if(properties.pversionId){
			treeId += (properties.pversionId + "-")
		}
		if(properties.milestoneId){
			treeId += (properties.milestoneId + "-")
		}
		treeId += targetObj.id
		history.treeId = treeId
		//-----------------------------记录treeId---------------------end
		history.audited = new Audited()
		history.save()

		if(history.errors.hasErrors()){
			def errorMsg=''
			history.errors.allErrors.each { errorMsg += it  }
			log.info("##${errorMsg}")
		}
	}

	/**
	 * 只记录路标子系统的创建或删除日志
	 *
	 * @param targetObj
	 * @param del boolean 是否是删除操作
	 */
	void logNotupdateHistory(Object targetObj, Boolean isDel) {
		def targertType = GuidepostObject.mappingClass(targetObj.class)
		if(!targertType){
			targertType = targetObj.class.name
		}

		def sf = new SimpleDateFormat("yyyy-MM-dd")
		def properties = targetObj.properties

		//-----------------------------开始记录日志---------------------------
		def changedContent
		if(isDel){
			changedContent="删除操作： "
		}else{
			changedContent="创建操作： "
		}

		if(properties.hasProperty('name')){
			changedContent += "名称： '${properties.name}'； "
		}

		properties.each {fieldName, fieldValue->
			if(!fieldValue || fieldName == 'name' || fieldName=='origins' || fieldName=='audited' || fieldName.endsWith("Id")|| fieldName.equals("productVersions")|| fieldName.equals("funcs")){
				return
			}

			//值如果是对象, 则对值再深加工一次
			if(fieldValue instanceof Enum){
				fieldValue = fieldValue?.label?:''

			}else if(fieldValue instanceof Date){
				fieldValue = fieldValue?sf.format(fieldValue):''

			}else if(fieldValue instanceof User){
				fieldValue = fieldValue?.realName?:''

			}else if(fieldValue.hasProperty("status")){//有 status属性, 则为路标对象, 一定有name属性
				fieldValue = fieldValue?.name?:''

			}else if(fieldName.equals("product")){
				fieldValue = fieldValue?.name?:''

			}else if(fieldValue instanceof ProductFunctionPool){
				fieldValue = fieldValue?.name?:''

			}

			//翻译成中文
			fieldName = translateChinese(fieldName)

			changedContent += "${fieldName}： '${fieldValue?:''}'； "
		}


		def history = new ProductHistory()
		history.targetType = targertType
		history.targetId = targetObj.id
		history.targetName = targetObj.name

		history.toSt = GuidepostStatus.CREATED
		if(isDel){
			history.fromSt = targetObj.status
			history.toSt = GuidepostStatus.DELETED
		}

		history.changedContent = changedContent

		//-----------------------------记录treeId---------------------start
		def treeId=""
		if(properties.guidepostId){
			treeId += (properties.guidepostId + "-")
		}
		if(properties.pversionId){
			treeId += (properties.pversionId + "-")
		}
		if(properties.milestoneId){
			treeId += (properties.milestoneId + "-")
		}
		treeId += targetObj.id
		history.treeId = treeId
		//-----------------------------记录treeId---------------------end
		history.audited = new Audited()
		history.save()


		if(history.errors.hasErrors()){
			def errorMsg=''
			history.errors.allErrors.each { errorMsg += it  }
			log.info("##${errorMsg}")
		}
	}


	def translateChinese(fieldName){
		def fieldNameLanguage = FieldNameLanguage.findByEnName(fieldName.toString())
		if(fieldNameLanguage){
			fieldName = fieldNameLanguage.chName
		}

		return fieldName
	}

	def getChangePath(targetId, targetType){

		def histories = ProductHistory.withCriteria{
			eq('targetType',  targetType)
			eq('targetId' , targetId.toLong())

			order('createdDate', 'asc')
		}

		def distinctStatusHis=[]
		def before=null
		histories.each{his->
			if(!before || before.toSt != his.toSt){
				distinctStatusHis << his
			}

			before = his
		}

		return distinctStatusHis

	}

	def exportGuidepostReport(guidepostId, startDate, endDate){
		//创建excel内容
		Workbook wb = new HSSFWorkbook()
		//------------------------------------------------------------表头表格样式
		CellStyle headStyle = wb.createCellStyle()
		Font font = wb.createFont()
		font.setFontHeightInPoints((short)9)
		font.setBoldweight(Font.BOLDWEIGHT_BOLD)
		headStyle.setFont(font)
		headStyle.setWrapText(true);
		headStyle.setAlignment(CellStyle.ALIGN_CENTER); // 左右居中
		headStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); // 上下居中
		headStyle.setFillForegroundColor(IndexedColors.SEA_GREEN.getIndex())
		headStyle.setFillPattern(CellStyle.SOLID_FOREGROUND)
		headStyle.setBorderBottom(CellStyle.BORDER_THIN)
		headStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex())
		headStyle.setBorderLeft(CellStyle.BORDER_THIN)
		headStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex())
		headStyle.setBorderRight(CellStyle.BORDER_THIN)
		headStyle.setRightBorderColor(IndexedColors.BLACK.getIndex())
		headStyle.setBorderTop(CellStyle.BORDER_THIN)
		headStyle.setTopBorderColor(IndexedColors.BLACK.getIndex())

		//内容表格样式
		CellStyle dataStyle = wb.createCellStyle()
		//dataStyle.setWrapText(true);
		dataStyle.setBorderBottom(CellStyle.BORDER_THIN)
		dataStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex())
		dataStyle.setBorderLeft(CellStyle.BORDER_THIN)
		dataStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex())
		dataStyle.setBorderRight(CellStyle.BORDER_THIN)
		dataStyle.setRightBorderColor(IndexedColors.BLACK.getIndex())
		dataStyle.setBorderTop(CellStyle.BORDER_THIN)
		dataStyle.setTopBorderColor(IndexedColors.BLACK.getIndex())
		dataStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER)
		//隔开行填充色样式
		CellStyle groupStyle = wb.createCellStyle()
		groupStyle.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex())
		groupStyle.setFillPattern(CellStyle.SOLID_FOREGROUND)
		groupStyle.setBorderBottom(CellStyle.BORDER_THIN)
		groupStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex())
		groupStyle.setBorderLeft(CellStyle.BORDER_THIN)
		groupStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex())
		groupStyle.setBorderRight(CellStyle.BORDER_THIN)
		groupStyle.setRightBorderColor(IndexedColors.BLACK.getIndex())
		groupStyle.setBorderTop(CellStyle.BORDER_THIN)
		groupStyle.setTopBorderColor(IndexedColors.BLACK.getIndex())

		Sheet sheet = wb.createSheet("路标变更报表")
		//------------------------------------------------表头
		RowNo rowNo = new RowNo()
		Row row = sheet.createRow(rowNo.no)
		row.setHeight((short) 15.625 * 30)

		Cell cell = row.createCell(0)
		cell.setCellValue('时间段')
		cell.setCellStyle(headStyle)

		cell = row.createCell(1)
		cell.setCellValue('变更对象')
		cell.setCellStyle(headStyle)

		cell = row.createCell(2)
		cell.setCellValue('变更内容')
		cell.setCellStyle(headStyle)

		cell = row.createCell(3)
		cell.setCellValue('变更时间')
		cell.setCellStyle(headStyle)

		cell = row.createCell(4)
		cell.setCellValue('变更人')
		cell.setCellStyle(headStyle)

		sheet.setColumnWidth(0,(short) 30*256);
		sheet.setColumnWidth(1,(short) 60*256);
		sheet.setColumnWidth(2,(short) 80*256);
		sheet.setColumnWidth(3,(short) 10*256);
		sheet.setColumnWidth(4,(short) 25*256);

		//路标历史变更
		def guidepostHistories = ProductHistory.withCriteria{
			eq('targetType',  GuidepostObject.GUIDEPOST.name())
			eq('targetId' , guidepostId)

			if(startDate){
				ge('createdDate', startDate)
				lt('createdDate', endDate + 1)
			}

			order('createdDate', 'asc')
		}

		def startHis=null
		def currentHis
		def length =  guidepostHistories.size()
		for(int i=0; i<length; i++){
			currentHis = guidepostHistories[i]
			if(startHis==null){//初始
				startHis=currentHis
			}

			if(i==(length-1)){
				onceChangeOfGuidepost(sheet, dataStyle, rowNo, guidepostId, startHis, currentHis)
				continue
			}

			if(guidepostHistories[i].toSt == GuidepostStatus.PUBLISHED){
				onceChangeOfGuidepost(sheet, dataStyle, rowNo, guidepostId, startHis, currentHis)
				startHis=currentHis
			}
		}

		return wb
	}


	def onceChangeOfGuidepost(sheet, dataStyle, rowNo, guidepostId, startHis, currentHis){
		//找一次变更
		def histories = ProductHistory.withCriteria{
			ge('createdDate', startHis.audited.createdDate)

			if(startHis != currentHis){
				le('createdDate', currentHis.audited.createdDate)
			}

			'in'('targetType', GuidepostObject.values()*.name())

			or{
				eq('targetId', guidepostId)
				like('treeId' , guidepostId + "-%")
			}

			order('treeId', 'asc')
			order('createdDate', 'asc')
		}

		def prefix=""
		//打印一次变更
		for(int i=0; i<histories.size();i++){
			if(histories[i].targetType == GuidepostObject.PVERSION.name()){
				prefix = PVERSION_PREFIX
			}else if(histories[i].targetType == GuidepostObject.MILESTONE.name()){
				prefix = MILESTON_PREFIX
			}else if(histories[i].targetType == GuidepostObject.FUNCTION.name()){
				prefix = FUNCTION_PREFIX
			}

			Row row = sheet.createRow(rowNo.no)
			Cell cell = row.createCell(0)
			cell.setCellStyle(dataStyle)
			if(i==0){//一个分组的第一行的第一个cell才有内容
				cell.setCellValue("${startHis.audited.createdDate.format('yyyy-MM-dd')} ${startHis.toSt.label} \r\n-> \r\n${histories[histories.size()-1].audited.createdDate.format('yyyy-MM-dd')} ${currentHis.toSt.label}")
			}

			cell = row.createCell(1)
			cell.setCellStyle(dataStyle)
			cell.setCellValue(prefix + GuidepostObject.valueOf(histories[i].targetType).label + ": " + histories[i].targetName)

			cell = row.createCell(2)
			cell.setCellStyle(dataStyle)
			cell.setCellValue(histories[i].changedContent)

			cell = row.createCell(3)
			cell.setCellStyle(dataStyle)
			cell.setCellValue(histories[i].audited.createdDate.format('yyyy-MM-dd hh:mm:ss'))

			cell = row.createCell(4)
			cell.setCellStyle(dataStyle)
			cell.setCellValue(histories[i].audited.createdBy)
		}

		sheet.addMergedRegion(new CellRangeAddress(rowNo.currentNo - histories.size() + 1,rowNo.currentNo, 0, 0));//合并单元格
	}

	public static class RowNo{
		private short rowNo=0

		public short getNo(){
			return rowNo++
		}

		public short getCurrentNo(){
			return rowNo-1
		}
	}

}
